/*
*    Author : heiden deng(dengjianquan@beyondcent.com)
*    2017/08/03
*    version 0.0.9
*    基于权重的round robin 负载均衡处理类方法定义
*/


#include "WeightRoundRobinLB.h"
#include "htsc_registry/url.h"
#include "htsc_registry/registry_utils.h"
#include "htsc_grpc_consumer_utils.h"
//addbyhuyn
#include "htsc_grpc_consumer_control_version.h"

WeightRoundRobinLB::WeightRoundRobinLB()
{
}


WeightRoundRobinLB::~WeightRoundRobinLB()
{
	cursors.clear();
}

void WeightRoundRobinLB::setProviders(std::map<std::string, std::vector<provider_t*> > *_providers) {
	this->providers = _providers;
}
void WeightRoundRobinLB::resetCursor(const char* sn) {
	std::map<std::string, int>::iterator iter = cursors.find(sn);
	if (iter == cursors.end())
	{
		cursors.insert(std::pair<std::string, int>(sn, -1));
		return;
	}
	iter->second = -1;
}
provider_t* WeightRoundRobinLB::chooseProvider(const char* sn, int step) {
	if (!sn)
	{
		return NULL;
	}
	int index = -1, index_org = -1;
	int size = 0;
	std::map<std::string, std::vector<provider_t*> >::iterator provider_iter = providers->find(sn);
	if (provider_iter == providers->end())
	{
		return NULL;
	}
	size = provider_iter->second.size();
	std::map<std::string, int>::iterator curIter = cursors.find(sn);
	if (curIter == cursors.end())
	{
		cursors.insert(std::pair<std::string, int>(sn, -1));
		curIter = cursors.find(sn);
	}

	index = curIter->second;

	index = (index + 1) % size;
	index_org = index;
	bool do_while = true;
	bool is_invalid = true;
	int index_valid = -1;
	//找出从index开始第一个不在黑名单中的provider,并且版本匹配的服务
	while (do_while)
	{
		is_invalid = is_provider_invalid(provider_iter->second[index]);
		if (is_invalid == false) { //查找到未禁用的服务
								   //根据服务名和版本号校验是否匹配
			if (htsc_grpc_consumer_control_version_match(provider_iter->second[index]->sInterface, provider_iter->second[index]->version) == true) {
				index_valid = index;
				break;   //找到未禁用，并且版本匹配的服务
			}
			else if (index_valid < 0) { //记录首个未禁用的服务,但是版本不匹配的服务
				index_valid = index;
			}
		}
		index = (index + 1) % size;
		if (index == index_org)
		{
			if (index_valid >= 0) {
				break;
			}
			else {
				return NULL;//没有合适的provider
			}
		}
	}
	curIter->second = index_valid;
	return clone_provider(provider_iter->second[index_valid]);
}